package logrus_util

import (
	"bytes"
	"fmt"
	"github.com/sirupsen/logrus"
	"sort"
	"strings"
)

type Formatter struct {
}

func (f Formatter) Format(entry *logrus.Entry) ([]byte, error) {
	buf := &bytes.Buffer{}

	// write time
	buf.WriteString(entry.Time.Format(DefaultTimestampFormat))

	// write level
	fmt.Fprintf(buf, " [%s] ", strings.ToUpper(entry.Level.String()))

	// write fields
	f.writeFields(buf, entry)

	// write message
	buf.WriteString(entry.Message)

	// write caller
	f.writeCaller(buf, entry)

	buf.WriteByte('\n')

	return buf.Bytes(), nil
}

func (f Formatter) writeFields(buf *bytes.Buffer, entry *logrus.Entry) {
	if len(entry.Data) != 0 {
		fields := make([]string, 0, len(entry.Data))
		for field := range entry.Data {
			fields = append(fields, field)
		}

		sort.Strings(fields)

		for _, field := range fields {
			fmt.Fprintf(buf, "[%s:%v] ", field, entry.Data[field])
		}
	}
}

func (f *Formatter) writeCaller(buf *bytes.Buffer, entry *logrus.Entry) {
	if entry.HasCaller() {
		fmt.Fprintf(buf, " (%s:%d %s)", entry.Caller.File, entry.Caller.Line, entry.Caller.Function)
	}
}
